function varargout = Behavior_box3(varargin)
% handle = Behavior_box3(varargin)
%
% For use with Behavior_Setup GUI.
%
% Necessary varargin inputs:
%   'experiment', 'BoxID','DBinfo'
%
% BoxID is simply the box number to be run.  Usually BoxID equals 1 or 2.
%
% experiment fields:
%
%
% Optional inputs:
%   'schedule'
%       NOTE: The BHVR_AddTrial function along with SCRATCH_make_schedule
%       script help create the schedule structure.
% schedule fields:
%   .writeparams  ...  cell array of RPvds parameter tag names to be
%                       written to before each trial.
%                      ex:
%                       {'stim_tagA','stim_tagB','acq_tag','stimtagC'}
%                       NOTE: the box id suffix will be added to each
%                       writeparams tag '~1' or '~2' automatically at
%                       runtime.
%   .readparams   ...  cell array of RPvds parameter tag names to be read
%                       after each trial.
%                       NOTE: the 'trial_index' tag is used to know which
%                       trial index is current.  If this is not specified
%                       in schedule.readparams then it will be added.
%   .writemodule  ...  numeric array with numbers corresponding to the
%                       experiment.modules index to update before each
%                       trial.  Must be the same length as the writeparams
%                       field.
%                     ex: [1 1 2 1] if stimulus module is index 1 and
%                     acquisition module is index 2
%   .readmodule   ...  numeric array with numbers corresponding to the
%                       experiment.modules index to read after each trial.
%                       Must be the same length as the readparams field.
%   .trials       ...  M x N matrix defining each trial for the experiment.
%                       M is the total number of trials and N is the number
%                       of parameter tags in the writeparams field and
%                       values in the writemodule fields.  Each column
%                       corresponds to each index in
%                       writeparams/writemodule fields.  Although this can
%                       matrix can be defined manually or by importing an
%                       Excel spreadsheet, the BHVR_AddTrial function
%                       has useful functionalities.
%   .OpExparams   ...  Optional field which is only used when running
%                       experiment with OpenEx interface.  Specify
%                       initializing parameters (ex: zSweepDur,etc...).
%                       These tags will be updated in 'PREVIEW' mode just
%                       before recording begins.  Specify as if it were a
%                       varargin for a function, ex:
%                       {'tag1',val1,'tag2',val2}
%                     ex: {'Stim.zSweepDur',1000}
%
%
% See also BHVR_AddTrial, SCRATCH_make_schedule
%
% DJS (c) 2010


% Last Modified by GUIDE v2.5 07-May-2010 10:55:23

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
    'gui_Singleton',  gui_Singleton, ...
    'gui_OpeningFcn', @Behavior_box3_OpeningFcn, ...
    'gui_OutputFcn',  @Behavior_box3_OutputFcn, ...
    'gui_LayoutFcn',  [] , ...
    'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before Behavior_box3 is made visible.
function Behavior_box3_OpeningFcn(hObject, eventdata, handles, varargin) %#ok<INUSL>
%--------------------------------------------------------------------------
%   Use varargin to parameterize behavior:
%       'experiment' ... next input must be an appropriate experiment
%       structure
%---------------------------------------------------------------------------
handles.output = hObject;

% set optional parameters
for i = 1:2:length(varargin)
    setappdata(hObject,varargin{i},varargin{i+1});
end

% Update handles structure
guidata(hObject, handles);

UpdateGUI(handles)

% --- Outputs from this function are returned to the command line.
function varargout = Behavior_box3_OutputFcn(hObject, eventdata, handles)  %#ok<INUSL>
varargout{1} = handles.output;



































%% Helper Functions
function SetTimerParameters(tobj,PV,handles)
%--------------------------------------------------------------------------
%   Set Timer Parameters for session. tobj is timer object
%--------------------------------------------------------------------------

% set defaults
if ~isfield(PV,'BusyMode'),      PV(1).BusyMode = 'queue';          end
if ~isfield(PV,'ExecutionMode'), PV(1).ExecutionMode = 'fixedRate'; end
if ~isfield(PV,'Period'),        PV(1).Period = 0.5;                end
if ~isfield(PV,'TimerFcn'),      PV(1).TimerFcn = {@TimerRunTimeFcn,handles}; end
if ~isfield(PV,'StopFcn'),       PV(1).StopFcn  = {@TimerStopFcn,handles};    end
if ~isfield(PV,'ErrorFcn'),      PV(1).ErrFcn   = {@TimerErrFcn,handles};     end
if ~isfield(PV,'TasksToExecute'),PV(1).TasksToExecute = 10^6;       end
if ~isfield(PV,'StartDelay'),    PV(1).StartDelay = 6;              end
set(tobj,PV);

function CheckParams(figh)
%--------------------------------------------------------------------------
%   Check various parameters
%--------------------------------------------------------------------------

TDTinfo    = getappdata(figh,'TDTinfo');
experiment = getappdata(figh,'experiment');
schedule   = getappdata(figh,'schedule');

% copy field so experiment structure does not need to be passed to every
% function
TDTinfo.useOpenEx = experiment.useOpenEx;
setappdata(figh,'TDTinfo',TDTinfo);

% add 'trial_index' RPvds parameter tag to schedule.readparams
for i = 1:length(schedule)
    if ~any(strcmp(schedule(i).readparams,'trial_index'))
        schedule(i).readparams{end+1} = 'trial_index';
        schedule(i).readmodule(end+1) = 1;
    end
    
end

if ~isfield(experiment,'AdaptiveTrials')
    experiment.AdaptiveTrials = false;
end

setappdata(figh,'experiment',experiment);
setappdata(figh,'TDTinfo',TDTinfo);
setappdata(figh,'schedule',schedule);









































%% GUI Stuff
function UpdateGUI(handles)
%--------------------------------------------------------------------------
%   Check current status of settings and update gui availability
%   accordingly.
%--------------------------------------------------------------------------

% TDT info menu
experiment = getappdata(handles.figure1,'experiment');
if experiment.useOpenEx
    set(handles.mnu_openex,'Checked','on');
else
    set(handles.mnu_openex,'Checked','off');
end

% Update Figure Name
% DBinfo = getappdata(handles.figure1,'DBinfo');

% schedule is needed to run experiment
if isappdata(handles.figure1,'SchedFN') ...
        && exist(getappdata(handles.figure1,'SchedFN'),'file');
    set(handles.mnu_run,'Enable','on');
else
    set(handles.mnu_run,'Enable','off');
end

% experiment control state
TDTinfo = getappdata(handles.figure1,'TDTinfo');
if ~isempty(TDTinfo) ...
        && isfield(TDTinfo,'STATE') ...
        && strcmp(TDTinfo.STATE,'RUNNING') % running/recording
    set(handles.mnu_run,'Label','Stop');
    set(handles.mnu_openex,'Enable','off');
else
    set(handles.mnu_run,'Label','Run');
    set(handles.mnu_openex,'Enable','on');
end

function UpdateSessionResults(trialstate,CurTIDX,BoxID,handles) %#ok<INUSD>
%--------------------------------------------------------------------------
%   Update 'Session Results' with hits, misses, false alarms, correct
%   rejects, d'
%   Returns response 'hit1','miss1','correct reject', or 'false alarm'
%
%   Trial Types
% Normal Trial  ...  0
% Catch Trial   ...  1
%
%   The data table (MachineState) in the RPvds file can be modified, but
%   must also be adjusted here.
%
%       Response Type              Value
% hit1                           ...   1
% miss1 (pre-gap; aka FA)        ...  -1
% miss1 (post-gap)               ...  -2
% Correct Reject                 ...   2
% False Alarm                    ...  -4
% miss1 (pre-gap on catch trial) ...  -3
%
% Reward: values < 0
% Punish: values > 0
%
%--------------------------------------------------------------------------
r = trialstate;

ms = sum(r == -2);
ht = sum(r == 1);
fa = sum(ismember(r,[-1,-3,-4]));
cr = sum(r == 2);

% d' = Z(hit1 rate) - Z(false alarm rate)
dp = ht/sum(ht|ms) - fa/sum(fa|cr);

eval(sprintf('set(handles.hit%d,''String'',''%d'');',BoxID,ht));
eval(sprintf('set(handles.miss%d,''String'',''%d'');',BoxID,ms));
eval(sprintf('set(handles.correct_reject%d,''String'',''%d'');',BoxID,cr));
eval(sprintf('set(handles.false_alarm%d,''String'',''%d'');',BoxID,fa));
eval(sprintf('set(handles.srpanel%d,''Title'',''Session Results (trial #%d)'');',BoxID,CurTIDX));

if ~isnan(dp) && ~isinf(dp)
    eval(sprintf('set(handles.d_prime%d,''String'',''d'''' = %2.2f'');',BoxID,dp));
end





















%% Timer Functions
function TimerStartFcn(hObject,events,handles) %#ok<INUSL>
%--------------------------------------------------------------------------
%   Setup Experiment.
%
%   Integrate with TDT system, either directly for behavior experiment
%   or indirectly using OpenEx for combined behavior and
%   electrophysiology experiments.
%--------------------------------------------------------------------------

set(handles.figure1,'Pointer','watch');

% reload the schedule
LoadSchedule(getappdata(handles.figure1,'SchedFN'),handles);

TDTinfo    = getappdata(handles.figure1,'TDTinfo');
experiment = getappdata(handles.figure1,'experiment');
schedule   = getappdata(handles.figure1,'schedule');

setappdata(handles.figure1,'schedule',schedule);

% backup dir
if ~isdir([experiment.resultsdir 'BACKUP\'])
    mkdir([experiment.resultsdir 'BACKUP\']);
end

if experiment.useOpenEx   % Running Behavior and Electrophysiology:
    %   Initialize OpenEx connection
    TDTinfo = InitializeOpenEx(TDTinfo,schedule);
    if strcmp(TDTinfo.STATE,'ERROR')
        set(handles.figure1,'Pointer','arrow');
        delete(hObject);
        return
    end

else    % Running Behavior only:
    TDTinfo = InitializeRPvds(experiment);
end

TDTinfo.useOpenEx = experiment.useOpenEx;

% schedule.result     = cell(2,1);
% schedule.trialstate = cell(2,1);

for i = 1:length(schedule)
    schedule(i).CurTIDX = 1;
    schedule(i).trialstate = [];
end

setappdata(handles.figure1,'TDTinfo', TDTinfo);
setappdata(handles.figure1,'schedule',schedule);

CheckParams(handles.figure1);

for BoxID = 1:2
    UpdateParams(1,schedule(BoxID),TDTinfo);
    UpdateGUI(handles);
end

cla(handles.axes1); cla(handles.axes2);

set(handles.figure1,'Pointer','arrow');

function TimerRunTimeFcn(hObject,events,handles) %#ok<INUSL,INUSD>
TDTinfo    = getappdata(handles.figure1,'TDTinfo');
schedule   = getappdata(handles.figure1,'schedule');
experiment = getappdata(handles.figure1,'experiment');

for BoxID = 1:length(schedule)
    [pn,pv] = RetrieveParams(TDTinfo,schedule(BoxID)); % read RPvds tag values
    ts = pv(strcmpi(pn,'trial_state'));
    ti = pv(strcmpi(pn,'trial_index'));

    if ti == 0, ti = 1; end

    if ti ~= schedule(BoxID).CurTIDX && ts ~= 0  % new trial: update parameters

        try
            
            S = schedule(BoxID);
            
            modc = mod(S.CurTIDX,size(S.trials,1));
            if modc == 0, modc = size(S.trials,1);   end

            % Record result of last trial
            S.trialstate(modc) = ts;
            
            % Update Display
            UpdateSessionResults(S.trialstate,modc,S.BoxID,handles);

            % backup session data in the case of hardware/software failure
            save([experiment.resultsdir 'BACKUP\' num2str(BoxID) '-' date '.mat'],'S');
            
            % Plot data
            feval(experiment.plotfunc,eval(sprintf('handles.axes%d',BoxID)), ...
                S,S.trialstate);

            % optionally run adaptive trials
            if isfield(S,'AdaptiveTrials') && isstruct(S.AdaptiveTrials)
                 S = AdaptiveTrials(S);
            end
            
            % wrap-around schedule
            modti = mod(ti,size(S.trials,1));
            if modti == 0, modti = size(S.trials,1); end
            
            % update RPvds parameters for next trial
            UpdateParams(modti,S,TDTinfo);
            
            
            
        catch
            % throw error message dialogue and save to error log
%             le = lasterror;
%             errordlg(sprintf('message\t:%s\n\n\nidentifier:\t%s\n', ...
%                 le.messsage,le.identifier),'ERROR','modal');
%             fid = fopen([experiment.resultsdir 'error_log.txt'],'a');
%             fprintf(fid,'date:%s\t\t%s\n\tmessage\t:%s\n\tidentifier:\t%s\n', ...
%                 date,mat2str(clock),le.messsage,le.identifier);
%             fclose(fid);
%             save([experiment.resultsdir 'error_log.txt'],'le','-ascii','-append');
    %             rethrow(lasterror)

        end

        S.CurTIDX = ti;

        
        schedule(BoxID) = S;
        setappdata(handles.figure1,'schedule',schedule);

    end
end

function TimerStopFcn(hObject,events,handles) %#ok<INUSL>
TDTinfo = getappdata(handles.figure1,'TDTinfo');

CloseTDTInterface(TDTinfo);

UpdateGUI(handles);

function TimerErrFcn(hObject,events,handles) %#ok<INUSL>
delete(hObject);

TDTinfo = getappdata(handles.figure1,'TDTinfo');

CloseTDTInterface(TDTinfo);

set(handles.mnu_run,'Label','Run');

UpdateGUI(handles);

rethrow(lasterror);

fprintf('\nTimer Error!\n')

errordlg('Timer Error!','Behavior_box3','modal');








%% Adaptive Trials
function S = AdaptiveTrials(S)
% Dynamically updates the schedule.trials based on adaptive parameters
%
% Requires S.AdaptiveTrials structure:
%  ex:
%   schedule.AdaptiveTrials.increment =  250; % in milliseconds
%   schedule.AdaptiveTrials.decrement = -250;
%   schedule.AdaptiveTrials.incrafter = 3; % trials
%   schedule.AdaptiveTrials.decrafter = 5;
%   schedule.AdaptiveTrials.min       = 1000; % in milliseconds
%   schedule.AdaptiveTrials.max       = 7000;
%   schedule.AdaptiveTrials.parameter = 'gap_delay';


AT = S.AdaptiveTrials;

PIDX = strcmp(AT.parameter,S.writeparams);

r = S.trialstate;

ms = r == -2;
ht = r == 1;
fa = ismember(r,[-1,-3,-4]);
cr = r == 2;

n = size(S.trials,1);   % current length of trials

v = S.trials(end,PIDX); % previous value

S.trials(end+1,~PIDX) = S.trials(end,~PIDX); % copy static parameters

if n >= AT.incrafter ...
        && all(S.trials(end-AT.incrafter+1,PIDX) == v) ...
        && (all(ht(end-AT.incrafter+1:end) ...
        | cr(end-AT.incrafter+1:end))) % check increment
    S.trials(end,PIDX) = AT.increment + v;
    fprintf('Box %d: ''%s'' increased (%g) to %g\n', ...
        S.BoxID,AT.parameter,AT.increment,S.trials(end,PIDX))

elseif n >= AT.decrafter ...
        && all(S.trials(end-AT.decrafter+1,PIDX) == v) ...
        && (all(ms(end-AT.decrafter+1:end) ...
        | fa(end-AT.decrafter+1:end))) % check decrement
    S.trials(end,PIDX) = AT.decrement + v;
    fprintf('Box %d: ''%s'' decreased (%g) to %g\n', ...
        S.BoxID,AT.parameter,AT.increment,S.trials(end,PIDX))

else % no change    
    S.trials(end,PIDX) = v;
    
end


if S.trials(end,PIDX) > AT.max, S.trials(end,PIDX) = AT.max; end
if S.trials(end,PIDX) < AT.min, S.trials(end,PIDX) = AT.min; end




















%% TDT interface
function TDTinfo = InitializeRPvds(expt)
%--------------------------------------------------------------------------
%   Create a connection (if one is not active) directly to modules (not
%   using OpenEx).  Load and Run RPvds files from the experiment structure.
%--------------------------------------------------------------------------
mods = expt.module;
if ~isfield(expt,'ct') || isempty(expt.ct), expt.ct = 'GB'; end

for i = 1:length(mods)
    module = mods(i);
    eval(sprintf('TDTinfo.module(%d).R = TDT_SetupRP(''%s'',%d,''%s'',''%s'');', ...
        i, module.type, module.id, expt.ct, module.path));
    TDTinfo.module(i).type = module.type;
end

TDTinfo.STATE  = 'RUNNING';

function TDTinfo = InitializeOpenEx(TDTinfo,S)
%--------------------------------------------------------------------------
%   Initialize connection with OpenEx, set 'PREVIEW' mode, and finally
%   update OpenEx parameters (schedule.OpExparams).
%--------------------------------------------------------------------------
[TT,tanks,TDTfig] = TDT_SetupTT(TDTinfo.TT);

TDTinfo.TT     = TT;
TDTinfo.tanks  = tanks;
TDTinfo.TDTfig = TDTfig;
TDTinfo.STATE  = 'STOPPED';

%   Select tank for recording.
seltank = SelectTank(TDTinfo);

if TDTinfo.DA.GetSysMode ~= 2
    %   Establish connection with OpenEx and Open Tank (seltank)
    [DA,curtank] = TDT_SetupDA('tank',seltank);

    %   Set OpenEx to 'PREVIEW'
    DA.SetSysMode(2);
    wait(3);
end

%   Check OpenEx is in 'PREVIEW' mode
if DA.GetSysMode ~= 2
    errordlg(sprintf([ ...
        'Unable to switch OpenEx to ''PREVIEW'' mode!\n\n', ...
        'Check OpenEx is open and the correct file is loaded']), ...
        'OpenEx Error','modal');

    TDTinfo.STATE = 'ERROR';
    return
end

if isfield(schedule,'OpExparams')
    for i = 1:2:length(S.OpExparams)
        DA.SetTargetVal(sprintf('%s~%d',S.OpExparams{i},S.BoxID), ...
            S.OpExparams{i+1});
    end
end

TDTinfo.DA = DA;
TDTinfo.curtank = curtank;
TDTinfo.STATE = 'PREVIEW';

function [pn,pv] = RetrieveParams(TDTinfo,S)
%--------------------------------------------------------------------------
%   Retrieve parameter tags from running modules as specified in the
%   schedule structure (see help Behavior_box3).
%--------------------------------------------------------------------------

pn = cell(size(S.readparams));
pv = nan(size(pn));
if TDTinfo.useOpenEx % using OpenEx interface
    for i = 1:length(S.readmodule)
        pn{i} = S.readparams{i};
        pv(i) = TDTinfo.DA.GetTagVal([ ...
            TDTinfo.module{ ...
            S.readmodule(i)},'.', ...
            S.readparams{i}, ...
            num2str(S.BoxID,'~%d')]);
    end

else % using RPco.x interface
    for i = 1:length(S.readmodule)
        pn{i} = S.readparams{i};
        pv(i) = TDTinfo.module(S.readmodule(i)).R.GetTagVal( ...
            [pn{i},num2str(S.BoxID,'~%d')]);
    end

end

function eos = UpdateParams(index,S,TDTinfo)
%--------------------------------------------------------------------------
%   Update RPvds parameters to 'index' trial based on schedule values.
% 
%   eos = UpdateParams(index,schedule,BoxID,TDTinfo);
%      > where session over returns true if index > size(schedule.trials,1)
%--------------------------------------------------------------------------

BoxID = S.BoxID;

if index > size(S.trials,1)
    eos = true;
else
    eos = false;
end

e = false(size(S.writemodule));

if TDTinfo.useOpenEx % using OpenEx interface
    for i = 1:length(S.writemodule)
        
        if any(strfind(S.writeparams{i},num2str(BoxID,'~%d')))
            wstr = [TDTinfo.module{ ...
            S.writemodule(i)},'.', ...
            S.writeparams{i}];
        else
            wstr = [TDTinfo.module{ ...
            S.writemodule(i)},'.', ...
            S.writeparams{i},num2str(BoxID,'~%d')];
        end
        
        e(i) = TDTinfo.DA.SetTargetVal(wstr, ...
            S.trials(index,i));
    end

else % using RPco.x interface

    if eos
        TDTinfo.module(S.writemodule(1)).R.SetTagVal( ...
            num2str(BoxID,'reset_count~%d'),1);
        pause(0.001)
        TDTinfo.module(S.writemodule(1)).R.SetTagVal( ...
            num2str(BoxID,'reset_count~%d'),0);
        index = 1;
    end
    
    for i = 1:length(S.writemodule)
        if any(strfind(S.writeparams{i},num2str(BoxID,'~%d')))
            wstr = S.writeparams{i};
        else
            wstr = [S.writeparams{i}, num2str(BoxID,'~%d')];
        end
        
        e(i) = TDTinfo.module(S.writemodule(i)).R.SetTagVal( ...
            wstr,S.trials(index,i));
        %         fprintf('%s = %g (%d)\n',[S.writeparams{i}, num2str(BoxID,'~%d')], ...
        %             S.trials(index,i),e(i))
       
    end
    
    TDTinfo.module(1).R.SoftTrg(BoxID);
end


% fprintf('warning: Parameter Tag ''%s'' was not updated\n', ...
%     schedule.writeparams{~e})

function TDTinfo = CloseTDTInterface(TDTinfo)
%--------------------------------------------------------------------------
%  ** MAY NOT BE ABLE TO HALT TDT MODULES IF MORE THAN ONE ANIMAL IS
%  RUNNING ON THE SAME SYSTEM.  THIS MAY NEED TO BE DONE MANUALLY BY USER
%  **
%
%   Halt TDT modules and close connection.
%--------------------------------------------------------------------------
if TDTinfo.useOpenEx % using OpenEx interface
    TDTinfo.DA.SetSysMode(1);
else % using RPco.x interface
    for i = 1:length(TDTinfo.module)
        TDTinfo.module(i).R.ClearCOF;
    end
end
TDTinfo.STATE = 'STOPPED';

function seltank = SelectTank(TDTinfo)
%--------------------------------------------------------------------------
%    Which tank should we record into?  (OpenEx only)
%--------------------------------------------------------------------------
if isempty(TDTinfo)
    TDTinfo = InitializeRPvds(experiment);
end

TT = TDTinfo.TT;

tanks = TDT_RegTanks(TT);
tanks{end+1} = '< New Tank >';
[seltank,ok] = TDT_TankSelect(TT,{'TankList',tanks});

if ~ok, return; end

if strcmp(seltank,'< New Tank >')
    uiwait(TDT_NewTank);
end

seltank = TDT_TankSelect(TT,{'TankList',tanks});

































%% GUI Callback
function mnu_load_schedule_Callback(hObject, eventdata, handles) %#ok<INUSL,DEFNU>
[filename,pathname] = uigetfile( ...
    {'*.mat','MAT-files (*.mat)'}, ...
    'Load Schedule File');

setappdata(handles.figure1,'SchedFN',fullfile(pathname,filename));

UpdateGUI(handles);

function LoadSchedule(filename,handles)
if ~ischar(filename), return; end

if ~exist(filename,'file'), return; end

load(filename);

if ~exist('schedule','var')
    errordlg('''schedule'' structure not found in file.','Invalid Schedule File');
    return
end
    
% duplicate schedule if there is only one
if length(schedule) == 1 %#ok<NODEF>
    schedule(2) = schedule;
end


for i = 1:length(schedule)
    schedule(i).BoxID = i;

    if ~isfield(schedule(i),'AdaptiveTrials')
        schedule(i).AdaptiveTrials = [];
    end
    
    if ~isstruct(schedule(i).AdaptiveTrials) % adaptive trials are handled differently
        k = 1;
        trials = [];
        for j = 1:schedule(i).nreps
            if schedule(i).randomize
                ind = randperm(size(schedule(i).trials,1));
                trials(k:k+length(ind)-1,:) = schedule(i).trials(ind,:);
                k = k + length(ind);
            end
        
        end
        
        schedule(i).trials = trials;
    end
end

setappdata(handles.figure1,'SchedFN',filename);
setappdata(handles.figure1,'schedule',schedule);


function mnu_run_Callback(hObject, eventdata, handles) %#ok<INUSL,INUSD,DEFNU>
%--------------------------------------------------------------------------
%   Start session timer
%--------------------------------------------------------------------------
experiment = getappdata(handles.figure1,'experiment');

if strcmp(get(hObject,'Label'),'Run')

    T = timer('Tag','BoxTimer', ...
        'Name','SessionTimer', ...
        'ExecutionMode','fixedSpacing', ...
        'BusyMode','queue', ...
        'Period',0.5, ...
        'TasksToExecute',10^6, ...
        'StartFcn',{@TimerStartFcn,handles}, ...
        'TimerFcn',{@TimerRunTimeFcn,handles}, ...
        'StopFcn', {@TimerStopFcn,handles}, ...
        'ErrorFcn',{@TimerErrFcn,handles});

    if isfield(experiment,'timerPV')
        SetTimerParameters(T,experiment.timerPV,handles);
    end

    set(handles.srpanel1,'Title','Session Results');
    set(handles.hit1,'String',0);
    set(handles.miss1,'String',0);
    set(handles.correct_reject1,'String',0);
    set(handles.false_alarm1,'String',0);
    set(handles.d_prime1,'String','d''');
    set(handles.srpanel2,'Title','Session Results');
    set(handles.hit2,'String',0);
    set(handles.miss2,'String',0);
    set(handles.correct_reject2,'String',0);
    set(handles.false_alarm2,'String',0);
    set(handles.d_prime2,'String','d''');

    start(T);
else
    T = timerfind('Tag','BoxTimer');
    if ~isempty(T)
        stop(T);
        delete(T);
    end
    TDTinfo = getappdata(handles.figure1,'TDTinfo');
    TDTinfo = CloseTDTInterface(TDTinfo);
    setappdata(handles.figure1,'TDTinfo',TDTinfo);
    UpdateGUI(handles);
end

function save_data1_Callback(hObject, eventdata, handles) %#ok<INUSL,DEFNU>
schedule   = getappdata(handles.figure1,'schedule');
experiment = getappdata(handles.figure1,'experiment');
feval(experiment.savefunc,schedule(1),experiment,1);

function save_data2_Callback(hObject, eventdata, handles) %#ok<INUSL,DEFNU>
schedule   = getappdata(handles.figure1,'schedule');
experiment = getappdata(handles.figure1,'experiment');
feval(experiment.savefunc,schedule(2),experiment,2);

function mnu_box1_Callback(hObject, eventdata, handles) %#ok<INUSL,DEFNU>
setappdata(handles.figure1,'BoxID',1);
UpdateGUI(handles);

function mnu_box2_Callback(hObject, eventdata, handles) %#ok<INUSL,DEFNU>
setappdata(handles.figure1,'BoxID',2);
UpdateGUI(handles);



